package com.ibeeking.found.cop.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.cop.b.rest.service.ICopAttachementService;
import com.ibeeking.found.cop.b.rest.service.IMsgMessageSopDetailService;
import com.ibeeking.found.cop.b.rest.service.IMsgMessageSopService;
import com.ibeeking.found.cop.service.common.bo.MsgSendRuleBO;
import com.ibeeking.found.cop.service.common.dos.*;
import com.ibeeking.found.cop.service.common.enums.WxCpMessageAssignStatusEnum;
import com.ibeeking.found.cop.service.common.param.CopAttachementParam;
import com.ibeeking.found.cop.service.common.param.MsgMessageSopDetailParam;
import com.ibeeking.found.cop.service.common.param.MsgMessageSopParam;
import com.ibeeking.found.cop.service.common.param.UniAttachParam;
import com.ibeeking.found.cop.service.common.query.MsgMessageSopPageQuery;
import com.ibeeking.found.cop.service.common.query.MsgMessageSopQuery;
import com.ibeeking.found.cop.service.common.vo.CopAttachementVO;
import com.ibeeking.found.cop.service.common.vo.MsgMessageSopDetailVO;
import com.ibeeking.found.cop.service.common.vo.MsgMessageSopVO;
import com.ibeeking.found.cop.service.common.vo.UniAttachVO;
import com.ibeeking.found.cop.service.mapper.*;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.date.DateUtil;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName MsgMessageSopServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class MsgMessageSopServiceImpl extends ServiceImpl<MsgMessageSopMapper, MsgMessageSopDO> implements IMsgMessageSopService {

    private static String DATE_FORMAT_YYYYMMDD = "yyyy-MM-dd";

    private static String DATE_FORMAT_HHMMSS = "HH:mm:ss";

    @Resource
    private MsgMessageSopMapper msgMessageSopMapper;

    @Resource
    private MsgMessageSopDetailMapper msgMessageSopDetailMapper;

    @Resource
    private IMsgMessageSopDetailService msgMessageSopDetailServiceImpl;

    @Resource
    private CopAttachementMapper copAttachementMapper;

    @Resource
    private ICopAttachementService copAttachementServiceImpl;

    @Resource
    private GroupMapper groupMapper;

    @Resource
    private GroupTagsRelMapper groupTagsRelMapper;

    @Override
    public List<MsgMessageSopVO> list(MsgMessageSopQuery query) {
        List<MsgMessageSopDO> entityDOS = msgMessageSopMapper.selectList(new LambdaQueryWrapper<MsgMessageSopDO>()
                .eq(query.getId() != null, MsgMessageSopDO::getId, query.getId())
                .like(StringUtils.isNotBlank(query.getName()), MsgMessageSopDO::getName, query.getName())
                .eq(query.getSendStatus() != null, MsgMessageSopDO::getSendStatus, query.getSendStatus())
                .orderByDesc(MsgMessageSopDO::getCreateTime)
        );
        List<MsgMessageSopVO> entityVOS = new ArrayList<>();
        if(Collections3.isNotEmpty(entityDOS)) {
            String tenantId = UserUtils.getTenantId();
            List<GroupDO> allGroupDOS = groupMapper.selectList(new LambdaQueryWrapper<GroupDO>());

            Map<Long, String> groupOwnerIdMapName = Collections3.isNotEmpty(allGroupDOS)?allGroupDOS.stream().collect(Collectors.toMap(GroupDO::getOwnerId, GroupDO::getName, (o, n) -> n)):null;
            Map<Long, String> groupIdMapName = Collections3.isNotEmpty(allGroupDOS)?allGroupDOS.stream().collect(Collectors.toMap(GroupDO::getId, GroupDO::getName, (o, n) -> n)):null;
            entityVOS = entityDOS.stream().map(x -> {
                MsgMessageSopVO msgMessageSopVO = BeanUtil.convertBean(x,MsgMessageSopVO.class);
                String sendRuleStr = x.getSendRule();
                List<String> sendScopeList = new ArrayList<>();
                if(StringUtils.isNotEmpty(sendRuleStr)){
                    MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRuleStr, MsgSendRuleBO.class);
                    if(msgSendRuleBO != null) {
                        msgMessageSopVO.setMsgSendRule(msgSendRuleBO);
                        if(msgSendRuleBO.getIsAllGroup() == 1){
                            sendScopeList.add("所有群");
                        }else{
                            List<String> ownerIdList = msgSendRuleBO.getGroupOwnerCodeList();
                            if(Collections3.isNotEmpty(ownerIdList)){
                                ownerIdList.stream().forEach(d->{
                                    Long ownerId = StringUtils.isNotEmpty(d)?Long.valueOf(d):null;
                                    if(ownerId!=null) {
                                        String groupName = groupOwnerIdMapName.get(ownerId);
                                        sendScopeList.add(groupName);
                                    }
                                });
                            }
                            List<Long> ownerTagList = msgSendRuleBO.getGroupTagsList();
                            if(Collections3.isNotEmpty(ownerTagList)){
                                List<GroupTagsRelDO> allGroupTagsRelDOS = groupTagsRelMapper.listByTagsIds(Integer.valueOf(tenantId), new HashSet<>(ownerTagList));
                                if(Collections3.isNotEmpty(allGroupTagsRelDOS)){
                                    allGroupTagsRelDOS.stream().forEach(d->{
                                        String groupName = groupIdMapName.get(d.getGroupId());
                                        sendScopeList.add(groupName);
                                    });
                                }
                            }
                        }
                    }
                }else{
                    MsgSendRuleBO msgSendRuleBO = new MsgSendRuleBO();
                    msgMessageSopVO.setMsgSendRule(msgSendRuleBO);
                }
                if(Collections3.isNotEmpty(sendScopeList)){
                    msgMessageSopVO.setSendScope(StringUtils.join(sendScopeList.toArray(),";"));
                }
                msgMessageSopVO.setSendStatusDesc(WxCpMessageAssignStatusEnum.getDescByCode(x.getSendStatus()));
                return msgMessageSopVO;
            }).collect(Collectors.toList());
        }
        return entityVOS;
    }

    @Override
    public Page<MsgMessageSopVO> pageList(MsgMessageSopPageQuery pageQuery) {
        LambdaQueryWrapper<MsgMessageSopDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(pageQuery.getId() != null, MsgMessageSopDO::getId, pageQuery.getId())
                .like(StringUtils.isNotBlank(pageQuery.getName()), MsgMessageSopDO::getName, pageQuery.getName())
                .eq(pageQuery.getSendStatus() != null, MsgMessageSopDO::getSendStatus, pageQuery.getSendStatus())
                .orderByDesc(MsgMessageSopDO::getCreateTime);
        Page<MsgMessageSopDO> entityDOPages = msgMessageSopMapper.selectPage(new Page<MsgMessageSopDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), wrapper);
        Page<MsgMessageSopVO> entityVOPages = BeanUtil.convertPage(entityDOPages, MsgMessageSopVO.class);
        if(entityVOPages!=null && entityVOPages.getSize()>0) {
            entityVOPages.getRecords().forEach(f -> {
                String sendRuleStr = f.getSendRule();
                if(StringUtils.isNotEmpty(sendRuleStr)){
                    MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRuleStr, MsgSendRuleBO.class);
                    f.setMsgSendRule(msgSendRuleBO);
                }else{
                    MsgSendRuleBO msgSendRuleBO = new MsgSendRuleBO();
                    f.setMsgSendRule(msgSendRuleBO);
                }
                f.setSendStatusDesc(WxCpMessageAssignStatusEnum.getDescByCode(f.getSendStatus()));
            });
        }
        return entityVOPages;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(MsgMessageSopParam param) {
        checkUnique(param);
        MsgMessageSopDO entityDO = BeanUtil.convertBean(param, MsgMessageSopDO.class);
        Long sopId = GenerateId.generateId();
        entityDO.setId(sopId);
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        MsgSendRuleBO msgSendRuleBO = param.getMsgSendRule();
        if(msgSendRuleBO != null){
            Integer isAllGroup = msgSendRuleBO.getIsAllGroup();
            if(isAllGroup == 1){
                msgSendRuleBO.setGroupTagsList(null);
                msgSendRuleBO.setGroupOwnerCodeList(null);
            }
            entityDO.setSendRule(JsonUtils.toJsonStr(msgSendRuleBO));
        }
        List<MsgMessageSopDetailParam> messageSopDetailParamList= param.getMessageSopDetails();
        if(Collections3.isNotEmpty(messageSopDetailParamList)){
            List<MsgMessageSopDetailDO> msgMessageSopDetailDOS = new ArrayList<>();
            List<CopAttachementParam> copAttachementParams = new ArrayList<>();
            for(MsgMessageSopDetailParam detailParam:messageSopDetailParamList){
                MsgMessageSopDetailDO msgMessageSopDetailDO = BeanUtil.convertBean(detailParam, MsgMessageSopDetailDO.class);
                Long sopDetailId = GenerateId.generateId();
                msgMessageSopDetailDO.setId(sopDetailId);
                msgMessageSopDetailDO.setSopId(sopId);
                msgMessageSopDetailDO.setCreateBy(UserUtils.getUserId());
                msgMessageSopDetailDO.setCreateTime(LocalDateTime.now());
                msgMessageSopDetailDO.setModifyTime(LocalDateTime.now());
                String sendDate = detailParam.getSendDate();
                String sendTime = detailParam.getSendTime();
                if(StringUtils.isNotEmpty(sendDate) && StringUtils.isNotEmpty(sendTime)){
                    LocalDateTime sendDateTime = DateUtil.strToLocalDateTime(sendDate.concat(" ").concat(sendTime));
                    msgMessageSopDetailDO.setSendDateTime(sendDateTime);
                }
                List<UniAttachParam> attachParamList = detailParam.getAttachements();
                if(Collections3.isNotEmpty(attachParamList)){
                    CopAttachementParam copAttachementParam = copAttachementServiceImpl.transerUniAttachementToCopAttachement(attachParamList);
                    if(copAttachementParam!=null){
                        copAttachementParam.setMessageId(sopDetailId);
                        copAttachementParams.add(copAttachementParam);
                    }
                }
                msgMessageSopDetailDOS.add(msgMessageSopDetailDO);
            }
            if(Collections3.isNotEmpty(copAttachementParams)) {
                copAttachementServiceImpl.batchAdd(copAttachementParams);
            }
            if(Collections3.isNotEmpty(msgMessageSopDetailDOS)) {
                msgMessageSopDetailMapper.insertBatchSomeColumn(msgMessageSopDetailDOS);
            }
        }
        return msgMessageSopMapper.insert(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(MsgMessageSopParam param) {
        Long sopId = param.getId();
        if(sopId == null) throw new BusinessException("获取前端参数出错！");
        MsgMessageSopDO entityDO = BeanUtil.convertBean(param, MsgMessageSopDO.class);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        MsgSendRuleBO msgSendRuleBO = param.getMsgSendRule();
        if(msgSendRuleBO != null){
            Integer isAllGroup = msgSendRuleBO.getIsAllGroup();
            if(isAllGroup == 1){
                msgSendRuleBO.setGroupTagsList(null);
                msgSendRuleBO.setGroupOwnerCodeList(null);
            }
            entityDO.setSendRule(JsonUtils.toJsonStr(msgSendRuleBO));
        }
        List<MsgMessageSopDetailParam> messageSopDetailParamList= param.getMessageSopDetails();
        if(Collections3.isNotEmpty(messageSopDetailParamList)){
            List<Long> needDeleteDetailIds = new ArrayList<>();
            List<Long> needDeleteDetailAttachIds = new ArrayList<>();
            List<CopAttachementParam> copAttachementParams = new ArrayList<>();
            List<MsgMessageSopDetailDO> needInsertDetailDOList = new ArrayList<>();
            List<MsgMessageSopDetailDO> needUpdateDetailDOList = new ArrayList<>();
            List<MsgMessageSopDetailDO> oldMsgMessageSopDetailDOS = msgMessageSopDetailMapper.selectList(new LambdaQueryWrapper<MsgMessageSopDetailDO>().eq(MsgMessageSopDetailDO::getSopId,sopId));
            List<Long> allOldDetailIdList = Collections3.isNotEmpty(oldMsgMessageSopDetailDOS)?oldMsgMessageSopDetailDOS.stream().map(MsgMessageSopDetailDO::getId).collect(Collectors.toList()):null;
            List<Long> allNewDetailIdList = messageSopDetailParamList.stream().map(MsgMessageSopDetailParam::getId).collect(Collectors.toList());
            if(Collections3.isNotEmpty(allOldDetailIdList)){
                HashSet<Long> allOldDetailIdSet = new HashSet<>(allOldDetailIdList);
                HashSet<Long> allNewDetailIdSet = new HashSet<>(allNewDetailIdList);
                allOldDetailIdSet.removeAll(allNewDetailIdSet);
                needDeleteDetailIds = new ArrayList<>(allOldDetailIdSet);
                needDeleteDetailAttachIds = new ArrayList<>(allOldDetailIdSet);
            }
            List<MsgMessageSopDetailParam> needInsertDetailList =  messageSopDetailParamList.stream().filter(d->(d.getId() == null)).collect(Collectors.toList());
            if(Collections3.isNotEmpty(needInsertDetailList)){
                needInsertDetailList.stream().forEach(d->{
                    MsgMessageSopDetailDO msgMessageSopDetailDO = BeanUtil.convertBean(d,MsgMessageSopDetailDO.class);
                    Long sopDetailId = GenerateId.generateId();
                    msgMessageSopDetailDO.setId(sopDetailId);
                    msgMessageSopDetailDO.setSopId(sopId);
                    msgMessageSopDetailDO.setCreateBy(UserUtils.getUserId());
                    msgMessageSopDetailDO.setCreateTime(LocalDateTime.now());
                    msgMessageSopDetailDO.setModifyTime(LocalDateTime.now());
                    String sendDate = d.getSendDate();
                    String sendTime = d.getSendTime();
                    if(StringUtils.isNotEmpty(sendDate) && StringUtils.isNotEmpty(sendTime)){
                        LocalDateTime sendDateTime = DateUtil.strToLocalDateTime(sendDate.concat(" ").concat(sendTime));
                        msgMessageSopDetailDO.setSendDateTime(sendDateTime);
                    }
                    List<UniAttachParam> attachParamList = d.getAttachements();
                    if(Collections3.isNotEmpty(attachParamList)){
                        CopAttachementParam copAttachementParam = copAttachementServiceImpl.transerUniAttachementToCopAttachement(attachParamList);
                        if(copAttachementParam!=null){
                            copAttachementParam.setMessageId(sopDetailId);
                            copAttachementParams.add(copAttachementParam);
                        }
                    }
                    needInsertDetailDOList.add(msgMessageSopDetailDO);
                });
            }
            List<MsgMessageSopDetailParam> needUpdateDetailList =  messageSopDetailParamList.stream().filter(d->(d.getId() != null)).collect(Collectors.toList());
            if(Collections3.isNotEmpty(needUpdateDetailList)){
                for(MsgMessageSopDetailParam d:needUpdateDetailList){
                    MsgMessageSopDetailDO msgMessageSopDetailDO = BeanUtil.convertBean(d,MsgMessageSopDetailDO.class);
                    Long sopDetailId = d.getId();
                    msgMessageSopDetailDO.setSopId(sopId);
                    msgMessageSopDetailDO.setModifyBy(UserUtils.getUserId());
                    msgMessageSopDetailDO.setModifyTime(LocalDateTime.now());
                    String sendDate = d.getSendDate();
                    String sendTime = d.getSendTime();
                    if(StringUtils.isNotEmpty(sendDate) && StringUtils.isNotEmpty(sendTime)){
                        LocalDateTime sendDateTime = DateUtil.strToLocalDateTime(sendDate.concat(" ").concat(sendTime));
                        msgMessageSopDetailDO.setSendDateTime(sendDateTime);
                    }
                    List<UniAttachParam> attachParamList = d.getAttachements();
                    if(Collections3.isNotEmpty(attachParamList)){
                        CopAttachementParam copAttachementParam = copAttachementServiceImpl.transerUniAttachementToCopAttachement(attachParamList);
                        if(copAttachementParam!=null){
                            copAttachementParam.setId(IdGenerator.getId());
                            copAttachementParam.setMessageId(sopDetailId);
                            copAttachementParams.add(copAttachementParam);
                        }
                    }
                    needDeleteDetailAttachIds.add(sopDetailId);
                    needUpdateDetailDOList.add(msgMessageSopDetailDO);
                };
            }
            if(Collections3.isNotEmpty(needDeleteDetailAttachIds)){
                copAttachementMapper.delete(new LambdaQueryWrapper<CopAttachementDO>().in(CopAttachementDO::getMessageId,needDeleteDetailAttachIds));
            }
            if(Collections3.isNotEmpty(copAttachementParams)){
                copAttachementServiceImpl.batchAdd(copAttachementParams);
            }
            if(Collections3.isNotEmpty(needDeleteDetailIds)){
                msgMessageSopDetailMapper.deleteBatchIds(needDeleteDetailIds);
            }
            if(Collections3.isNotEmpty(needUpdateDetailDOList)){
                msgMessageSopDetailServiceImpl.updateBatch(needUpdateDetailDOList);
            }
            if(Collections3.isNotEmpty(needInsertDetailDOList)){
                msgMessageSopDetailMapper.insertBatchSomeColumn(needInsertDetailDOList);
            }
        }
        return msgMessageSopMapper.updateById(entityDO) > 0;
    }

    @Override
    public MsgMessageSopVO view(Long id) {
        MsgMessageSopDO entityDO = msgMessageSopMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        MsgMessageSopVO entityVO = BeanUtil.convertBean(entityDO, MsgMessageSopVO.class);
        if(entityVO != null) {
            //LocalDateTime sendDateTime = entityDO.;
            String sendRuleStr = entityVO.getSendRule();
            if(StringUtils.isNotEmpty(sendRuleStr)){
                MsgSendRuleBO msgSendRuleBO = JsonUtils.fromJson(sendRuleStr, MsgSendRuleBO.class);
                entityVO.setMsgSendRule(msgSendRuleBO);
            }else{
                MsgSendRuleBO msgSendRuleBO = new MsgSendRuleBO();
                entityVO.setMsgSendRule(msgSendRuleBO);
            }
            List<MsgMessageSopDetailDO>  messageSopDetailDOList = msgMessageSopDetailMapper.selectList(new LambdaQueryWrapper<MsgMessageSopDetailDO>().eq(MsgMessageSopDetailDO::getSopId, id));
            if(Collections3.isNotEmpty(messageSopDetailDOList)){
               List<MsgMessageSopDetailVO> messageSopDetails = messageSopDetailDOList.stream().map(d->{
                   MsgMessageSopDetailVO msgMessageSopDetailVO = BeanUtil.convertBean(d, MsgMessageSopDetailVO.class);
                   LocalDateTime sendDateTime = d.getSendDateTime();
                   String sendDate = DateUtil.parseStr(sendDateTime,DATE_FORMAT_YYYYMMDD);
                   String sendTime = DateUtil.parseStr(sendDateTime,DATE_FORMAT_HHMMSS);
                   msgMessageSopDetailVO.setSendDate(sendDate);
                   msgMessageSopDetailVO.setTabTitle(sendDate);
                   msgMessageSopDetailVO.setSendTime(sendTime);
                   CopAttachementVO copAttachementVO = copAttachementServiceImpl.queryByMessageId(d.getId());
                   if(null != copAttachementVO) {
                       List<UniAttachVO> uniAttachVOS = copAttachementServiceImpl.transerCopAttachementToUniAttachement(copAttachementVO);
                       msgMessageSopDetailVO.setAttachements(uniAttachVOS);
                   }
                   return msgMessageSopDetailVO;
               }).collect(Collectors.toList());
                entityVO.setMessageSopDetails(messageSopDetails);
            }
            entityVO.setSendStatusDesc(WxCpMessageAssignStatusEnum.getDescByCode(entityDO.getSendStatus()));
        }
        return entityVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        MsgMessageSopDO entityDO = msgMessageSopMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        entityDO.setSendStatus(status);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return msgMessageSopMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        MsgMessageSopDO entityDO = msgMessageSopMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        List<MsgMessageSopDetailDO> msgMessageSopDetailDOS = msgMessageSopDetailMapper.selectList(new LambdaQueryWrapper<MsgMessageSopDetailDO>().eq(MsgMessageSopDetailDO::getSopId, id));
        if(Collections3.isNotEmpty(msgMessageSopDetailDOS)){
            List<Long> detailIds = msgMessageSopDetailDOS.stream().map(MsgMessageSopDetailDO::getId).collect(Collectors.toList());
            msgMessageSopDetailMapper.deleteBatchIds(detailIds);
            copAttachementMapper.delete(new LambdaQueryWrapper<CopAttachementDO>().in(CopAttachementDO::getMessageId,detailIds));
        }
        return msgMessageSopMapper.deleteById(id) > 0;
    }
    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(MsgMessageSopParam param) {
        if (param == null) {
            throw new BusinessException("当前记录不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<MsgMessageSopDO> queryWrapper = new LambdaQueryWrapper<MsgMessageSopDO>()
                .ne(param.getId() != null, MsgMessageSopDO::getId, param.getId())
                .eq(MsgMessageSopDO::getName, param.getName());
        List<MsgMessageSopDO> dos = msgMessageSopMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的记录!");
        }
    }

}
